package com.sky.skyopsserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.skyopsserver.domain.Application;
import com.sky.skyopsserver.domain.Environment;
import com.sky.skyopsserver.enums.ResponseCodeEnum;
import com.sky.skyopsserver.exception.BizException;
import com.sky.skyopsserver.mapper.ApplicationMapper;
import com.sky.skyopsserver.mapper.EnvironmentMapper;
import com.sky.skyopsserver.service.EnvironmentService;
import com.sky.skyopsserver.vos.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 环境信息服务实现类
 * 
 * @author Administrator
 * @description 针对表【environment(环境表)】的数据库操作Service实现
 * @createDate 2025-09-13 17:43:04
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EnvironmentServiceImpl extends ServiceImpl<EnvironmentMapper, Environment>
        implements EnvironmentService {

    private final ApplicationMapper applicationMapper;
    
    // 环境编码格式正则表达式
    private static final Pattern CODE_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_-]*$");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addEnvironment(EnvironmentAddReqVO reqVO) {
        log.info("开始添加环境，环境编码: {}, 环境名称: {}", reqVO.getCode(), reqVO.getName());
        
        // 验证环境编码格式
        if (!validateEnvironmentCode(reqVO.getCode())) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_CODE_INVALID);
        }
        
        // 检查环境编码是否已存在
        if (checkEnvironmentCodeExists(reqVO.getCode(), null)) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_CODE_EXISTS);
        }
        
        // 检查环境名称是否已存在
        if (checkEnvironmentNameExists(reqVO.getName(), null)) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NAME_EXISTS);
        }
        
        // 构建环境实体
        Environment environment = Environment.builder()
                .code(reqVO.getCode())
                .name(reqVO.getName())
                .remark(reqVO.getRemark())
                .createTime(LocalDateTime.now())
                .build();
        
        // 保存到数据库
        boolean saved = save(environment);
        if (!saved) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_ADD_FAILED);
        }
        
        log.info("环境添加成功，环境ID: {}", environment.getId());
        return environment.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateEnvironment(EnvironmentUpdateReqVO reqVO) {
        log.info("开始更新环境，环境ID: {}", reqVO.getId());
        
        // 检查环境是否存在
        Environment existingEnvironment = getById(reqVO.getId());
        if (Objects.isNull(existingEnvironment)) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NOT_EXISTS);
        }
        
        // 验证环境编码格式
        if (!validateEnvironmentCode(reqVO.getCode())) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_CODE_INVALID);
        }
        
        // 检查环境编码是否已被其他环境使用
        if (checkEnvironmentCodeExists(reqVO.getCode(), reqVO.getId())) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_CODE_EXISTS);
        }
        
        // 检查环境名称是否已被其他环境使用
        if (checkEnvironmentNameExists(reqVO.getName(), reqVO.getId())) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NAME_EXISTS);
        }
        
        // 更新环境信息
        Environment environment = new Environment();
        BeanUtils.copyProperties(reqVO, environment);
        
        boolean updated = updateById(environment);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_UPDATE_FAILED);
        }
        
        log.info("环境更新成功，环境ID: {}", reqVO.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteEnvironment(Long id) {
        log.info("开始删除环境，环境ID: {}", id);
        
        // 检查环境是否存在
        Environment existingEnvironment = getById(id);
        if (Objects.isNull(existingEnvironment)) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NOT_EXISTS);
        }
        
        // 检查环境下是否有应用
        Long applicationCount = getApplicationCountByEnvironmentId(id);
        if (applicationCount > 0) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_IN_USE);
        }
        
        boolean deleted = removeById(id);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_DELETE_FAILED);
        }
        
        log.info("环境删除成功，环境ID: {}", id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteEnvironment(List<Long> ids) {
        log.info("开始批量删除环境，环境ID列表: {}", ids);
        
        if (CollectionUtils.isEmpty(ids)) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        
        // 检查所有环境是否存在
        List<Environment> existingEnvironments = listByIds(ids);
        if (existingEnvironments.size() != ids.size()) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NOT_EXISTS);
        }
        
        // 检查环境下是否有应用
        Map<Long, Long> applicationCountMap = getApplicationCountByEnvironmentIds(ids);
        List<Long> environmentsInUse = applicationCountMap.entrySet().stream()
                .filter(entry -> entry.getValue() > 0)
                .map(Map.Entry::getKey)
                .toList();
        
        if (!environmentsInUse.isEmpty()) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_IN_USE);
        }
        
        boolean deleted = removeByIds(ids);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_DELETE_FAILED);
        }
        
        log.info("环境批量删除成功，删除数量: {}", ids.size());
        return true;
    }

    @Override
    public EnvironmentRspVO getEnvironmentById(Long id) {
        log.info("查询环境详情，环境ID: {}", id);
        
        Environment environment = getById(id);
        if (Objects.isNull(environment)) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NOT_EXISTS);
        }
        
        EnvironmentRspVO rspVO = new EnvironmentRspVO();
        BeanUtils.copyProperties(environment, rspVO);
        
        // 设置应用数量
        Long applicationCount = getApplicationCountByEnvironmentId(id);
        rspVO.setApplicationCount(applicationCount);
        
        return rspVO;
    }

    @Override
    public IPage<EnvironmentRspVO> getEnvironmentPage(EnvironmentPageReqVO reqVO) {
        log.info("分页查询环境列表，查询条件: {}", reqVO);
        
        // 构建分页对象
        Page<Environment> page = new Page<>(reqVO.getCurrent(), reqVO.getSize());
        
        // 构建查询条件
        LambdaQueryWrapper<Environment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(reqVO.getCode()), Environment::getCode, reqVO.getCode())
                   .like(StringUtils.hasText(reqVO.getName()), Environment::getName, reqVO.getName())
                   .like(StringUtils.hasText(reqVO.getRemark()), Environment::getRemark, reqVO.getRemark())
                   .orderByDesc(Environment::getCreateTime);
        
        // 执行分页查询
        IPage<Environment> environmentPage = page(page, queryWrapper);
        
        // 获取所有环境的应用数量
        List<Long> environmentIds = environmentPage.getRecords().stream()
                .map(Environment::getId)
                .collect(Collectors.toList());
        Map<Long, Long> applicationCountMap = getApplicationCountByEnvironmentIds(environmentIds);
        
        // 转换为响应VO
        IPage<EnvironmentRspVO> rspPage = environmentPage.convert(environment -> {
            EnvironmentRspVO rspVO = new EnvironmentRspVO();
            BeanUtils.copyProperties(environment, rspVO);
            rspVO.setApplicationCount(applicationCountMap.getOrDefault(environment.getId(), 0L));
            return rspVO;
        });
        
        log.info("分页查询环境列表完成，总记录数: {}", rspPage.getTotal());
        return rspPage;
    }

    @Override
    public List<EnvironmentOptionRspVO> getAllEnvironmentOptions() {
        log.info("查询所有环境选项");
        
        List<Environment> environments = list(new LambdaQueryWrapper<Environment>()
                .orderByAsc(Environment::getCode));
        
        // 获取所有环境的应用数量
        List<Long> environmentIds = environments.stream()
                .map(Environment::getId)
                .collect(Collectors.toList());
        Map<Long, Long> applicationCountMap = getApplicationCountByEnvironmentIds(environmentIds);
        
        return environments.stream()
                .map(environment -> convertToOptionVO(environment, applicationCountMap.getOrDefault(environment.getId(), 0L)))
                .collect(Collectors.toList());
    }

    @Override
    public List<EnvironmentOptionRspVO> getEnvironmentOptionsWithApps() {
        log.info("查询有应用的环境选项");
        
        // 先获取有应用的环境ID
        List<Long> environmentIdsWithApps = applicationMapper.selectList(new LambdaQueryWrapper<Application>()
                        .select(Application::getId) // 这里应该是环境相关字段，但Application表中没有环境字段，需要根据实际业务调整
                        .groupBy(Application::getId))
                .stream()
                .map(Application::getId)
                .collect(Collectors.toList());
        
        if (CollectionUtils.isEmpty(environmentIdsWithApps)) {
            return new ArrayList<>();
        }
        
        List<Environment> environments = listByIds(environmentIdsWithApps);
        Map<Long, Long> applicationCountMap = getApplicationCountByEnvironmentIds(environmentIdsWithApps);
        
        return environments.stream()
                .map(environment -> convertToOptionVO(environment, applicationCountMap.getOrDefault(environment.getId(), 0L)))
                .sorted(Comparator.comparing(EnvironmentOptionRspVO::getCode))
                .collect(Collectors.toList());
    }

    @Override
    public List<EnvironmentOptionRspVO> getEmptyEnvironmentOptions() {
        log.info("查询空环境选项");
        
        // 获取所有环境
        List<Environment> allEnvironments = list();
        
        // 获取有应用的环境ID（需要根据实际业务调整）
        Set<Long> environmentIdsWithApps = new HashSet<>(); // 这里需要根据实际业务逻辑实现
        
        // 过滤出空环境
        return allEnvironments.stream()
                .filter(environment -> !environmentIdsWithApps.contains(environment.getId()))
                .map(environment -> convertToOptionVO(environment, 0L))
                .sorted(Comparator.comparing(EnvironmentOptionRspVO::getCode))
                .collect(Collectors.toList());
    }

    @Override
    public EnvironmentStatisticsRspVO getEnvironmentStatistics() {
        log.info("获取环境统计信息");
        
        // 环境总数
        long totalCount = count();
        
        // 应用总数（需要根据实际业务调整）
        long totalApplicationCount = applicationMapper.selectCount(new LambdaQueryWrapper<>());
        
        // 有应用的环境数量（需要根据实际业务调整）
        long environmentsWithAppsCount = 0; // 这里需要根据实际业务逻辑实现
        
        // 空环境数量
        long emptyEnvironmentsCount = totalCount - environmentsWithAppsCount;
        
        // 本月新增环境数量
        YearMonth currentMonth = YearMonth.now();
        LocalDateTime monthStart = currentMonth.atDay(1).atStartOfDay();
        LocalDateTime monthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59);
        
        long monthlyAddedCount = count(new LambdaQueryWrapper<Environment>()
                .between(Environment::getCreateTime, monthStart, monthEnd));
        
        // 平均每环境应用数
        double avgAppsPerEnvironment = totalCount > 0 ? (double) totalApplicationCount / totalCount : 0.0;
        
        return EnvironmentStatisticsRspVO.builder()
                .totalCount(totalCount)
                .environmentsWithAppsCount(environmentsWithAppsCount)
                .emptyEnvironmentsCount(emptyEnvironmentsCount)
                .monthlyAddedCount(monthlyAddedCount)
                .totalApplicationCount(totalApplicationCount)
                .avgAppsPerEnvironment(Math.round(avgAppsPerEnvironment * 100.0) / 100.0)
                .build();
    }

    @Override
    public Boolean checkEnvironmentCodeExists(String code, Long excludeId) {
        LambdaQueryWrapper<Environment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Environment::getCode, code);
        
        if (Objects.nonNull(excludeId)) {
            queryWrapper.ne(Environment::getId, excludeId);
        }
        
        return count(queryWrapper) > 0;
    }

    @Override
    public Boolean checkEnvironmentNameExists(String name, Long excludeId) {
        LambdaQueryWrapper<Environment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Environment::getName, name);
        
        if (Objects.nonNull(excludeId)) {
            queryWrapper.ne(Environment::getId, excludeId);
        }
        
        return count(queryWrapper) > 0;
    }

    @Override
    public EnvironmentRspVO getEnvironmentByCode(String code) {
        log.info("根据编码查询环境，环境编码: {}", code);
        
        Environment environment = getOne(new LambdaQueryWrapper<Environment>()
                .eq(Environment::getCode, code));
        
        if (Objects.isNull(environment)) {
            throw new BizException(ResponseCodeEnum.ENVIRONMENT_NOT_EXISTS);
        }
        
        EnvironmentRspVO rspVO = new EnvironmentRspVO();
        BeanUtils.copyProperties(environment, rspVO);
        
        // 设置应用数量
        Long applicationCount = getApplicationCountByEnvironmentId(environment.getId());
        rspVO.setApplicationCount(applicationCount);
        
        return rspVO;
    }

    @Override
    public List<EnvironmentRspVO> searchEnvironmentByName(String name) {
        log.info("根据名称模糊查询环境，关键字: {}", name);
        
        List<Environment> environments = list(new LambdaQueryWrapper<Environment>()
                .like(StringUtils.hasText(name), Environment::getName, name)
                .orderByAsc(Environment::getCode));
        
        // 获取应用数量
        List<Long> environmentIds = environments.stream()
                .map(Environment::getId)
                .collect(Collectors.toList());
        Map<Long, Long> applicationCountMap = getApplicationCountByEnvironmentIds(environmentIds);
        
        return environments.stream()
                .map(environment -> {
                    EnvironmentRspVO rspVO = new EnvironmentRspVO();
                    BeanUtils.copyProperties(environment, rspVO);
                    rspVO.setApplicationCount(applicationCountMap.getOrDefault(environment.getId(), 0L));
                    return rspVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<EnvironmentRspVO> searchEnvironmentByCode(String code) {
        log.info("根据编码模糊查询环境，关键字: {}", code);
        
        List<Environment> environments = list(new LambdaQueryWrapper<Environment>()
                .like(StringUtils.hasText(code), Environment::getCode, code)
                .orderByAsc(Environment::getCode));
        
        // 获取应用数量
        List<Long> environmentIds = environments.stream()
                .map(Environment::getId)
                .collect(Collectors.toList());
        Map<Long, Long> applicationCountMap = getApplicationCountByEnvironmentIds(environmentIds);
        
        return environments.stream()
                .map(environment -> {
                    EnvironmentRspVO rspVO = new EnvironmentRspVO();
                    BeanUtils.copyProperties(environment, rspVO);
                    rspVO.setApplicationCount(applicationCountMap.getOrDefault(environment.getId(), 0L));
                    return rspVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public Long getApplicationCountByEnvironmentId(Long environmentId) {
        // 这里需要根据实际业务逻辑实现，假设Application表中有environment_id字段;
        // return applicationMapper.selectCount(new LambdaQueryWrapper<Application>();
        //         .eq(Application::getEnvironmentId, environmentId));
        return 0L; // 临时返回0，需要根据实际业务调整
    }

    @Override
    public Map<Long, Long> getApplicationCountByEnvironmentIds(List<Long> environmentIds) {
        if (CollectionUtils.isEmpty(environmentIds)) {
            return new HashMap<>();
        }
        
        // 这里需要根据实际业务逻辑实现
        // 临时返回空Map，需要根据实际业务调整
        Map<Long, Long> applicationCountMap = new HashMap<>();
        environmentIds.forEach(id -> applicationCountMap.put(id, 0L));
        return applicationCountMap;
    }

    @Override
    public Boolean validateEnvironmentCode(String code) {
        return StringUtils.hasText(code) && CODE_PATTERN.matcher(code).matches();
    }

    @Override
    public List<String> getAllEnvironmentCodes() {
        log.info("获取所有环境编码列表");
        
        return baseMapper.selectList(new LambdaQueryWrapper<Environment>()
                        .select(Environment::getCode)
                        .orderByAsc(Environment::getCode))
                .stream()
                .map(Environment::getCode)
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getAllEnvironmentNames() {
        log.info("获取所有环境名称列表");
        
        return baseMapper.selectList(new LambdaQueryWrapper<Environment>()
                        .select(Environment::getName)
                        .orderByAsc(Environment::getName))
                .stream()
                .map(Environment::getName)
                .collect(Collectors.toList());
    }

    /**
     * 转换为选项VO
     * 
     * @param environment 环境实体
     * @param applicationCount 应用数量
     * @return 选项VO
     */
    private EnvironmentOptionRspVO convertToOptionVO(Environment environment, Long applicationCount) {
        return EnvironmentOptionRspVO.builder()
                .id(environment.getId())
                .code(environment.getCode())
                .name(environment.getName())
                .applicationCount(applicationCount)
                .remark(environment.getRemark())
                .build();
    }
}




